package com.jintian.smart.kernel.flowable.controller;

import com.jintian.smart.kernel.core.flow.IFlowOperation;
import com.jintian.smart.kernel.core.flow.IProcessOperation;
import com.jintian.smart.kernel.core.flow.IProcessStarter;
import com.jintian.smart.kernel.core.flow.ProcessControl;
import com.jintian.smart.kernel.core.web.RestResultWrapper;
import com.jintian.smart.kernel.flowable.api.PermissionService;
import com.jintian.smart.kernel.flowable.common.utils.BeanUtils;
import com.jintian.smart.kernel.flowable.domain.entity.ActHiTaskInst;
import com.jintian.smart.kernel.flowable.domain.view.FlowBizVo;
import com.jintian.smart.kernel.flowable.flowable.service.impl.TaskQueryHandler;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Schema;
import org.flowable.engine.ProcessEngine;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskInfo;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 流程实例相关
 */
@RestResultWrapper
@RestController
@RequestMapping("/flow/instance")
@Schema(description = "流程实例")
@Transactional
public class InstanceController {
    protected static Logger logger = LoggerFactory.getLogger(InstanceController.class);
    @Autowired
    private IProcessOperation<List<TaskInfo>> processOperation;

    @Autowired
    private IFlowOperation<FlowBizVo> flowOperation;

    @Autowired
    private IProcessStarter<List<TaskInfo>> processStarter;

    @Autowired
    private ProcessEngine processEngine;

    @Autowired
    private TaskQueryHandler taskQueryHandler;

    @Autowired
    private PermissionService permissionService;

    @RequestMapping(value = "/start", method = RequestMethod.POST)
    @ResponseBody
    @Operation(summary = "启动流程实例__通过流程定义name", description = "实例启动成功，返回当前活动任务，如果部署流程模板时指定了tenantId，那么调用此方法也要指定")
    @Parameters(value = {@Parameter(name = "process", in = ParameterIn.DEFAULT, description = "流程定义ID"),
            @Parameter(name = "businessKey", in = ParameterIn.DEFAULT, description = "业务对象ID"),
            @Parameter(name = "tenantId", in = ParameterIn.DEFAULT, description = "系统标识(租户)"),
            @Parameter(name = "processControl", in = ParameterIn.DEFAULT, description = "流程控制")})
    public Object startByName(String process, String businessKey, String tenantId, @Nullable @RequestBody ProcessControl processControl) throws Exception {
        List<TaskInfo> list = processStarter.start(process, businessKey, processControl);
        List<ActHiTaskInst> actHiTaskInst = BeanUtils.copyList(list, ActHiTaskInst.class);
        return actHiTaskInst;
    }

    @RequestMapping(value = "/suspend", method = RequestMethod.POST)
    @ResponseBody
    @Operation(summary = "挂起流程实例")
    @Parameters(value = {@Parameter(name = "processInstanceId", in = ParameterIn.DEFAULT, description = "流程实例ID"),
            @Parameter(name = "processControl", in = ParameterIn.DEFAULT, description = "流程控制")})
    public Object suspendById(String processInstanceId, @Nullable @RequestBody ProcessControl processControl) throws Exception {
        processOperation.suspend(processInstanceId, processControl);
        return "执行成功";
    }

    @RequestMapping(value = "/resume", method = RequestMethod.POST)
    @ResponseBody
    @Operation(summary = "激活流程实例")
    @Parameters(value = {@Parameter(name = "processInstanceId", in = ParameterIn.DEFAULT, description = "流程实例ID"),
            @Parameter(name = "processControl", in = ParameterIn.DEFAULT, description = "流程控制")})
    public Object activateById(String processInstanceId, @Nullable @RequestBody ProcessControl processControl) throws Exception {
        processOperation.resume(processInstanceId, processControl);
        TaskEntity task = taskQueryHandler.getPrincipalTask(processInstanceId);
        return task.getId();
    }

    @RequestMapping(value = "/abort", method = RequestMethod.POST)
    @ResponseBody
    @Operation(summary = "流程终止")
    @Parameters(value = {@Parameter(name = "processInstanceId", in = ParameterIn.DEFAULT, description = "流程实例ID"),
            @Parameter(name = "processControl", in = ParameterIn.DEFAULT, description = "流程控制")})
    public Object abort(String processInstanceId, @Nullable @RequestBody ProcessControl processControl) throws Exception {
        processOperation.abort(processInstanceId, processControl);
        return "执行成功";
    }

    @RequestMapping(value = "/delete", method = RequestMethod.POST)
    @ResponseBody
    @Operation(summary = "删除实例")
    @Parameters(value = {@Parameter(name = "processInstanceId", in = ParameterIn.DEFAULT, description = "流程实例ID"),
            @Parameter(name = "processControl", in = ParameterIn.DEFAULT, description = "流程控制")})
    public Object delete(String processInstanceId, @Nullable @RequestBody ProcessControl processControl) throws Exception {
        processOperation.delete(processInstanceId, processControl);
        return "执行成功";
    }

    @RequestMapping(value = "/empty", method = RequestMethod.GET)
    @ResponseBody
    @Operation(summary = "清空所有实例")
    public Object empty() throws Exception {
        processOperation.empty();
        return "执行成功";
    }

    @RequestMapping(value = "/getByBizId", method = RequestMethod.GET)
    @ResponseBody
    @Operation(summary = "通过业务实体Id获取流程实例")
    @Parameters(value = {@Parameter(name = "bizId", in = ParameterIn.DEFAULT, description = "业务实体Id"),
            @Parameter(name = "bizClass", in = ParameterIn.DEFAULT, description = "业务实体类"),
            @Parameter(name = "process", in = ParameterIn.DEFAULT, description = "流程定义key")})
    public Object getByBizId(String bizId, String bizClass, String process) throws Exception {
        return flowOperation.query(bizId, bizClass, process);

    }

    @RequestMapping(value = "/queryExecutors", method = RequestMethod.GET)
    @ResponseBody
    @Operation(summary = "查询任务执行者")
    @Parameters(value = {@Parameter(name = "processInstanceId", in = ParameterIn.DEFAULT, description = "流程实例ID")})
    public Object queryExecutors(String processInstanceId) {
        List<Task> tasks = processEngine.getTaskService().createTaskQuery().processInstanceId(processInstanceId).includeIdentityLinks().list();
        return tasks.stream().collect(Collectors.toMap(task -> task.getTaskDefinitionKey(), task -> permissionService.getCanExecutor(task)));
    }
}
